#include "VideoDecoderThread.h"
#include <QDebug>
#include "mpp.h"
#include <iostream>

VideoDecoderThread::VideoDecoderThread(QObject *parent)
    : QThread(parent)
{
}

VideoDecoderThread::~VideoDecoderThread()
{
    stop();
    wait(); // 等待线程结束
}

void VideoDecoderThread::setVideoFile(const QString &filePath)
{
    QMutexLocker locker(&mutex);
    videoFilePath = filePath;
}

void VideoDecoderThread::stop()
{
    QMutexLocker locker(&mutex);
    isRunning = false;
}

void VideoDecoderThread::pause(bool paused)
{
    QMutexLocker locker(&mutex);
    isPaused = paused;
}

bool VideoDecoderThread::initializeDecoder()
{
    // 打开视频文件
    if (avformat_open_input(&formatCtx, videoFilePath.toStdString().c_str(), nullptr, nullptr) < 0) {
        emit errorOccurred("无法打开视频文件");
        return false;
    }

    // 查找视频流
    if (avformat_find_stream_info(formatCtx, nullptr) < 0) {
        emit errorOccurred("无法获取视频流信息");
        return false;
    }

    videoStreamIndex = -1;
    for (unsigned int i = 0; i < formatCtx->nb_streams; i++) {
        if (formatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
            videoStreamIndex = i;
            break;
        }
    }

    if (videoStreamIndex == -1) {
        emit errorOccurred("未找到视频流");
        return false;
    }

    // 优先尝试 RKMPP 解码器
    const AVCodec *codec = avcodec_find_decoder_by_name("h264_rkmpp");
    if (!codec) {
        emit errorOccurred("无法找到rkmpp解码器");
        codec = avcodec_find_decoder(formatCtx->streams[videoStreamIndex]->codecpar->codec_id);
        if (!codec) {
            emit errorOccurred("未找到解码器");
            return false;
        }
    }

    codecCtx = avcodec_alloc_context3(codec);
    if (!codecCtx) {
        emit errorOccurred("无法分配解码器上下文");
        return false;
    }

    // 配置 RKMPP 硬件解码（如果使用）
    if (codec->id == AV_CODEC_ID_H264 && strstr(codec->name, "rkmpp")) {
        av_opt_set(codecCtx->priv_data, "device", "/dev/mpp_service", 0);
    } else{
        emit errorOccurred("配置RKMPP失败");
    }

    if (avcodec_parameters_to_context(codecCtx, formatCtx->streams[videoStreamIndex]->codecpar) < 0) {
        emit errorOccurred("无法复制解码器参数");
        return false;
    }

    if (avcodec_open2(codecCtx, codec, nullptr) < 0) {
        emit errorOccurred("无法打开解码器");
        return false;
    }

    frame = av_frame_alloc();
    rgbFrame = av_frame_alloc();
    if (!frame || !rgbFrame) {
        emit errorOccurred("无法分配帧");
        return false;
    }

    // 分配 RGB 缓冲区 和 设置 AVFrame rgbFrame格式
    int numBytes = av_image_get_buffer_size(AV_PIX_FMT_RGB24, codecCtx->width, codecCtx->height, 1);
    rgbBuffer = (uint8_t *)av_malloc(numBytes * sizeof(uint8_t));
    av_image_fill_arrays(rgbFrame->data, rgbFrame->linesize, rgbBuffer, AV_PIX_FMT_RGB24,
                         codecCtx->width, codecCtx->height, 1);

    // 初始化格式转换上下文
    swsCtx = sws_getContext(codecCtx->width, codecCtx->height, codecCtx->pix_fmt,
                            codecCtx->width, codecCtx->height, AV_PIX_FMT_RGB24,
                            SWS_BILINEAR, nullptr, nullptr, nullptr);
    if (!swsCtx) {
        emit errorOccurred("无法初始化格式转换上下文");
        return false;
    }

    return true;
}

void VideoDecoderThread::cleanup()
{
    if (swsCtx) {
        sws_freeContext(swsCtx);
        swsCtx = nullptr;
    }
    if (rgbBuffer) {
        av_free(rgbBuffer);
        rgbBuffer = nullptr;
    }
    if (frame) {
        av_frame_free(&frame);
        frame = nullptr;
    }
    if (rgbFrame) {
        av_frame_free(&rgbFrame);
        rgbFrame = nullptr;
    }
    if (codecCtx) {
        avcodec_free_context(&codecCtx);
        codecCtx = nullptr;
    }
    if (formatCtx) {
        avformat_close_input(&formatCtx);
        formatCtx = nullptr;
    }
}

void VideoDecoderThread::run()
{
    {
        QMutexLocker locker(&mutex);
        isRunning = true;
        isPaused = false;
    }

    if (!initializeDecoder()) {
        cleanup();
        return;
    }

    AVPacket packet;
    av_init_packet(&packet);
    packet.data = nullptr;
    packet.size = 0;

    AVRational timeBase = formatCtx->streams[videoStreamIndex]->time_base;
    AVRational frameRateRational = formatCtx->streams[videoStreamIndex]->r_frame_rate;
    if (frameRateRational.num == 0 || frameRateRational.den == 0) {
        frameRateRational = formatCtx->streams[videoStreamIndex]->avg_frame_rate;
    }
    double frameRate = av_q2d(frameRateRational);
    double frameIntervalMs = frameRate > 0 ? (1000.0 / frameRate) * 0.65 : (1000.0 / 30.0); 

    std::cout << "帧率为" << frameRate << "  帧间隔为 " << frameIntervalMs << std::endl; 
    while (isRunning) {
        if (isPaused) {
            msleep(10); // 暂停时降低 CPU 占用
            continue;
        }

        int ret = av_read_frame(formatCtx, &packet);
        if (ret < 0) {
            emit playbackFinished();
            break;
        }

        if (packet.stream_index == videoStreamIndex) {
            ret = avcodec_send_packet(codecCtx, &packet);
            if (ret < 0) {
                qDebug() << "发送数据包失败，错误码：" << ret;
                av_packet_unref(&packet);
                continue;
            }

            while (isRunning && !isPaused) {
                ret = avcodec_receive_frame(codecCtx, frame);
                if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
                    break;
                } else if (ret < 0) {
                    qDebug() << "接收帧失败，错误码：" << ret;
                    break;
                }

                if (frame->width <= 0 || frame->height <= 0) {
                    qDebug() << "无效的帧分辨率：" << frame->width << "x" << frame->height;
                    continue;
                }

                int lines = sws_scale(swsCtx, frame->data, frame->linesize, 0, frame->height,
                                      rgbFrame->data, rgbFrame->linesize);
                if (lines <= 0) {
                    qDebug() << "sws_scale 转换失败，返回行数：" << lines;
                    continue;
                }

                QImage image(rgbFrame->data[0], codecCtx->width, codecCtx->height,
                             rgbFrame->linesize[0], QImage::Format_RGB888);
                if (!image.isNull()) {
                    emit frameReady(image);
                }

                // 根据帧率控制解码速度
                msleep(static_cast<unsigned long>(frameIntervalMs));
            }
        }

        av_packet_unref(&packet);
    }

    cleanup();
}